package vmo;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;

public class Tile {
	public enum TileType{VOID,FLOOR,WALL,RAMP,FLUID,BOUNDS};
	public TileType m_type;
	public short m_material;
	public short m_imagenumber;
	public boolean m_enclosed,m_atmospherics;
	public byte m_facing;
	public byte m_widget;
	
	public Tile(TileType type, short material)
	{
		m_enclosed=false;
		m_type=type;
		m_material=material;
		m_facing=0;
	}
	
	public Tile(DataInputStream stream) throws IOException
	{
		setTypewithByte(stream.readByte());
		if (m_type!=TileType.VOID)
		{
			m_material=stream.readShort();
			m_facing=stream.readByte();		
			m_widget=stream.readByte();
		}
		else
		{
			m_widget=Byte.MIN_VALUE;
		}
	}
	
	public void Save(DataOutputStream stream) throws IOException
	{
		stream.writeByte(getTypeByte());
		if (m_type!=TileType.VOID)
		{
			stream.writeShort(m_material);
			stream.writeByte(m_facing);
			stream.writeByte(m_widget);
		}
	}
	
	public void setFacing(byte b)
	{
		m_facing=b;
	}
	
	public void CalcImageNum()
	{
		switch (m_type)
		{
			case VOID:
			m_imagenumber=0;
			break;
			case FLOOR:
			if (m_enclosed)
			{
				m_imagenumber=(short) ((m_material*16)+2);				
			}
			else
			{
				m_imagenumber=(short) ((m_material*16)+1);				
			}
			break;
			
			case WALL:
			m_imagenumber=(short) ((m_material*16)+3);
			break;

			case FLUID:
			m_imagenumber=(short) ((m_material*16)+16);
			break;	
			
			case RAMP:
			//need to calculate adjacent tiles?
			CalcRamp();	
			break;
		}
		
	}
	
	void CalcRamp()
	{
		if (m_enclosed)
		{
			m_imagenumber=(short) ((m_material*16)+12+m_facing);				
			
		}
		else
		{
			m_imagenumber=(short) ((m_material*16)+4+m_facing);		
			
		}
	}
	
	byte getTypeByte()
	{
		byte add=0;
		if (m_enclosed)
		{
			add=8;
		}
		switch (m_type)
		{
		case VOID:
			return (byte) (0+add);
		case FLOOR:
			return (byte) (1+add);
		case WALL:
			return (byte) (2+add);
		case RAMP:
			return (byte) (3+add);
		case FLUID:
			return (byte) (4+add);		
		}
		return 0;
	}
	
	void setTypewithByte(byte b)
	{
		if ((b & 8)==0)
		{
			m_enclosed=false;
		}
		else
		{
			m_enclosed=true;
			b=(byte) (b-8);
		}
		switch(b)
		{
		case 0:
			m_type=TileType.VOID;
			break;
		case 1:
			m_type=TileType.FLOOR;
			break;
		case 2:
			m_type=TileType.WALL;
			break;
		case 3:
			m_type=TileType.RAMP;
			break;
		case 4:
			m_type=TileType.FLUID;
			break;		
		}
		
		
	}
	
	public void Encode(ByteBuffer buffer)
	{
		//encode type
		buffer.put(getTypeByte());

		//encode material
		buffer.putShort(m_material);
		
		buffer.put(m_facing);
		
		buffer.put(m_widget);
	}
	
	public Tile(ByteBuffer buffer)
	{
		setTypewithByte(buffer.get());
		
		m_material=buffer.getShort();
		
		m_facing=buffer.get();
		
		m_widget=buffer.get();
	}
}
